#!/bin/bash

# ===================================================================
# 一键部署 MySQL 8.4.3 一主两从集群（Docker + GTID + SSL 复制）
# 支持自动配置、证书生成、主从同步
# ===================================================================

set -euo pipefail
IFS=$'\n\t'

# =============== 配置参数 ===============
ROOT_PASSWORD="sx123ZY"
REPL_PASSWORD="sx123ZY"
INIT_DB="sx_txj"

MASTER_ID=1
SLAVE1_ID=2
SLAVE2_ID=3

MASTER_IP="172.21.0.10"
SLAVE1_IP="172.21.0.11"
SLAVE2_IP="172.21.0.12"

COMPOSE_FILE="docker-compose.yml"
SSL_DIR="./ssl"
DATA_DIR="./master-data"
CONFIG_DIR="./master"

# =============== 清理旧数据 ===============
echo "🧹 清理旧数据..."
docker-compose down -v > /dev/null 2>&1 || true
rm -rf ./master-data/* ./slave1-data/* ./slave2-data/*
rm -rf ./master ./slave1 ./slave2
mkdir -p ./master ./slave1 ./slave2
mkdir -p ./master-data ./slave1-data ./slave2-data
mkdir -p "$SSL_DIR"

# =============== 生成主节点 my.cnf ===============
cat > ./master/my.cnf << 'EOF'
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-do-db = sx_txj
# binlog-do-db = sx_db_user （可重复多行）
binlog_expire_logs_seconds = 604800
gtid_mode = ON
enforce-gtid-consistency = ON

# SSL 配置
ssl-ca = /etc/mysql/ssl/ca.pem
ssl-cert = /etc/mysql/ssl/server-cert.pem
ssl-key = /etc/mysql/ssl/server-key.pem

# 复制设置
binlog_format = ROW
log_slave_updates = ON

[client]
ssl-ca = /etc/mysql/ssl/ca.pem
ssl-cert = /etc/mysql/ssl/client-cert.pem
ssl-key = /etc/mysql/ssl/client-key.pem
EOF

# =============== 生成从节点 my.cnf ===============
cat > ./slave1/my.cnf << 'EOF'
[mysqld]
server-id = 2
log-bin = mysql-bin
binlog-do-db = sx_txj
# binlog-do-db = sx_db_user （可重复多行）
binlog_expire_logs_seconds = 604800
gtid_mode = ON
enforce-gtid-consistency = ON
read_only = ON
relay_log = relay-bin

# SSL 配置
ssl-ca = /etc/mysql/ssl/ca.pem
ssl-cert = /etc/mysql/ssl/server-cert.pem
ssl-key = /etc/mysql/ssl/server-key.pem

# 复制设置
binlog_format = ROW
log_slave_updates = ON

[client]
ssl-ca = /etc/mysql/ssl/ca.pem
ssl-cert = /etc/mysql/ssl/client-cert.pem
ssl-key = /etc/mysql/ssl/client-key.pem
EOF

cat > ./slave2/my.cnf << 'EOF'
[mysqld]
server-id = 3
log-bin = mysql-bin
binlog-do-db = sx_txj
# binlog-do-db = sx_db_user （可重复多行）
binlog_expire_logs_seconds = 604800
gtid_mode = ON
enforce-gtid-consistency = ON
read_only = ON
relay_log = relay-bin

# SSL 配置
ssl-ca = /etc/mysql/ssl/ca.pem
ssl-cert = /etc/mysql/ssl/server-cert.pem
ssl-key = /etc/mysql/ssl/server-key.pem

# 复制设置
binlog_format = ROW
log_slave_updates = ON

[client]
ssl-ca = /etc/mysql/ssl/ca.pem
ssl-cert = /etc/mysql/ssl/client-cert.pem
ssl-key = /etc/mysql/ssl/client-key.pem
EOF

# =============== 生成 docker-compose.yml ===============
cat > "$COMPOSE_FILE" << EOF
version: '3.8'

networks:
  mysql-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.21.0.0/24

services:
  mysql-master:
    image: mysql:8.4.3
    container_name: mysql-master
    ports:
      - "13306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: $ROOT_PASSWORD
      MYSQL_DATABASE: $INIT_DB
    volumes:
      - ./master/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./master-data:/var/lib/mysql
      - ./ssl:/etc/mysql/ssl
    networks:
      mysql-net:
        ipv4_address: $MASTER_IP
    command: mysqld --ssl-ca=/etc/mysql/ssl/ca.pem --ssl-cert=/etc/mysql/ssl/server-cert.pem --ssl-key=/etc/mysql/ssl/server-key.pem
    restart: unless-stopped

  mysql-slave1:
    image: mysql:8.4.3
    container_name: mysql-slave1
    ports:
      - "13307:3306"
    environment:
      MYSQL_ROOT_PASSWORD: $ROOT_PASSWORD
    volumes:
      - ./slave1/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./slave1-data:/var/lib/mysql
      - ./ssl:/etc/mysql/ssl
    networks:
      mysql-net:
        ipv4_address: $SLAVE1_IP
    command: mysqld --ssl-ca=/etc/mysql/ssl/ca.pem --ssl-cert=/etc/mysql/ssl/server-cert.pem --ssl-key=/etc/mysql/ssl/server-key.pem
    restart: unless-stopped
    depends_on:
      - mysql-master

  mysql-slave2:
    image: mysql:8.4.3
    container_name: mysql-slave2
    ports:
      - "13308:3306"
    environment:
      MYSQL_ROOT_PASSWORD: $ROOT_PASSWORD
    volumes:
      - ./slave2/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./slave2-data:/var/lib/mysql
      - ./ssl:/etc/mysql/ssl
    networks:
      mysql-net:
        ipv4_address: $SLAVE2_IP
    command: mysqld --ssl-ca=/etc/mysql/ssl/ca.pem --ssl-cert=/etc/mysql/ssl/server-cert.pem --ssl-key=/etc/mysql/ssl/server-key.pem
    restart: unless-stopped
    depends_on:
      - mysql-master
EOF

# =============== 生成 SSL 证书 ===============
echo "🔐 生成 SSL 证书..."
cd "$SSL_DIR" || exit 1

# 1. CA 证书
openssl genrsa -out ca-key.pem 2048 > /dev/null 2>&1
openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca.pem -subj "/CN=MySQL CA" > /dev/null 2>&1

# 2. 服务器证书
openssl req -newkey rsa:2048 -nodes -keyout server-key.pem -out server-req.pem -subj "/CN=mysql-server" > /dev/null 2>&1
openssl rsa -in server-key.pem -out server-key.pem > /dev/null 2>&1
openssl x509 -req -in server-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem > /dev/null 2>&1

# 3. 客户端证书（用于复制）
openssl req -newkey rsa:2048 -nodes -keyout client-key.pem -out client-req.pem -subj "/CN=mysql-client" > /dev/null 2>&1
openssl rsa -in client-key.pem -out client-key.pem > /dev/null 2>&1
openssl x509 -req -in client-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 02 -out client-cert.pem > /dev/null 2>&1

# 4. 验证
openssl verify -CAfile ca.pem server-cert.pem client-cert.pem > /dev/null 2>&1 && echo "✅ SSL 证书生成成功"

# 设置证书权限
chmod 644 *.pem

cd - > /dev/null

# =============== 启动 Docker 容器 ===============
echo "🚀 启动 MySQL 集群..."
docker-compose up -d

# 等待主库 MySQL 就绪
echo "⏳ 等待主库 MySQL 初始化完成..."
until docker exec mysql-master mysqladmin --silent -uroot -p"$ROOT_PASSWORD" ping &>/dev/null; do
    echo "🟡 等待主库启动..."
    sleep 5
done
echo "✅ 主库已就绪"

# 检查主节点 SSL 状态
echo "🔐 检查主节点 SSL 状态..."
docker exec mysql-master mysql -uroot -p"$ROOT_PASSWORD" -e "SHOW VARIABLES LIKE '%ssl%';"

# 等待数据库 sx_txj 被创建
echo "⏳ 等待数据库 sx_txj 创建..."
until docker exec mysql-master mysql -uroot -p"$ROOT_PASSWORD" -e "USE $INIT_DB;" &>/dev/null; do
    echo "🟡 等待数据库 $INIT_DB..."
    sleep 5
done
echo "✅ 数据库 $INIT_DB 已创建"

# =============== 配置主从复制 ===============
setup_replication() {
    local slave_name=$1
    local slave_ip=$2

    echo "🔁 配置 $slave_name 复制..."

    # 等待从库启动
    until docker exec "$slave_name" mysqladmin --silent -uroot -p"$ROOT_PASSWORD" ping &>/dev/null; do
        echo "🟡 等待 $slave_name 启动..."
        sleep 5
    done

    # 检查从节点 SSL 状态
    echo "🔐 检查 $slave_name SSL 状态..."
    docker exec "$slave_name" mysql -uroot -p"$ROOT_PASSWORD" -e "SHOW VARIABLES LIKE '%ssl%';"

    docker exec -i "$slave_name" mysql -uroot -p"$ROOT_PASSWORD" << EOF
STOP REPLICA;
RESET REPLICA ALL;
CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='$MASTER_IP',
  SOURCE_USER='repl',
  SOURCE_PASSWORD='$REPL_PASSWORD',
  SOURCE_SSL=1,
  SOURCE_SSL_CA='/etc/mysql/ssl/ca.pem',
  SOURCE_SSL_CERT='/etc/mysql/ssl/client-cert.pem',
  SOURCE_SSL_KEY='/etc/mysql/ssl/client-key.pem',
  SOURCE_AUTO_POSITION=1;
START REPLICA;
EOF
}

# 在主节点创建复制用户（先删除已存在的用户）
echo "🔐 在主节点创建复制用户..."
docker exec -i mysql-master mysql -uroot -p"$ROOT_PASSWORD" << EOF
DROP USER IF EXISTS 'repl'@'%';
CREATE USER 'repl'@'%' IDENTIFIED BY '$REPL_PASSWORD' REQUIRE SSL;
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
EOF

# 配置两个从节点
setup_replication "mysql-slave1" "$SLAVE1_IP"
setup_replication "mysql-slave2" "$SLAVE2_IP"

# 等待复制同步
echo "⏳ 等待复制同步..."
sleep 15

# =============== 验证复制状态 ===============
echo "🔍 验证主从复制状态..."

check_replica() {
    local container=$1
    echo "📊 $container 状态："
    docker exec -i "$container" mysql -uroot -p"$ROOT_PASSWORD" -e "SHOW REPLICA STATUS\G" | grep -E "(Slave_IO_Running|Slave_SQL_Running|Last_Error|Last_IO_Error|Last_SQL_Error|Replica_IO_State)"
    echo "----------------------------"
}

check_replica "mysql-slave1"
check_replica "mysql-slave2"

# =============== 测试数据同步 ===============
echo "🧪 测试数据同步..."
docker exec -i mysql-master mysql -uroot -p"$ROOT_PASSWORD" << EOF
USE $INIT_DB;
CREATE TABLE IF NOT EXISTS test_rep (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
INSERT INTO test_rep (name) VALUES ('Auto Deploy Test');
EOF

sleep 5

echo "✅ 数据同步测试结果："
docker exec -i mysql-slave1 mysql -uroot -p"$ROOT_PASSWORD" -e "USE $INIT_DB; SELECT * FROM test_rep;"

# =============== 完成 ===============
echo "🎉 部署完成！"
echo "🔗 主节点: 127.0.0.1:13306 (root/sx123ZY)"
echo "🔗 从节点1: 127.0.0.1:13307"
echo "🔗 从节点2: 127.0.0.1:13308"
echo "📄 配置目录: ./master, ./slave1, ./slave2"
echo "💾 数据目录: ./master-data, ./slave1-data, ./slave2-data"
echo "🔐 SSL 证书: ./ssl/"